// Copyright 2023 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/prctl.h>
#include <sys/time.h>
#include <fcntl.h>
#include <thread>
#include <iostream>
#include <signal.h>
#include "CommandParser.h"
#include "HealthChecker.h"
#include "RapidJson.h"
#include "Log.h"

#define MASTER_LOG_4_PROPERTIES_DIR "/opt/master/conf"
#define MASTER_LOG_4_PROPERTIES "/opt/master/conf/log.properties"
#define LOG_TIME_OUT 5000
#define MAIN_THREAD_SLEEP_TIME 10*1000*1000


static int generateLogDir(std::string inPath)
{
    struct stat theStatBuffer;
    if (stat(inPath.c_str(), &theStatBuffer) == -1) {
        if (mkdir(inPath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
            return ENC_FAIL;
    }

    return ENC_OK;
}

static void ShowUsage()
{
    printf("\nUsage: ./MasterServer  [Options...]\n\n");
    printf("Options:\n");
    printf("    -c '<path>'                           %s\n",
           "the service.conf path,you use default configuration in dir ffmpegEncode,"
           "if not config it will use the ./master.conf");
    printf("    -d                            %s\n", "run on backend");
}

void runHttpServer(std::string privateIp, std::string healthCheckUrl, uint16_t healthCheckPort) {
    auto router = oatpp::web::server::HttpRouter::createShared();
    router->route("GET", healthCheckUrl.c_str(), std::make_shared<HealthChecker>());
    auto connectionHandler = oatpp::web::server::HttpConnectionHandler::createShared(router);
    auto connectionProvider = oatpp::network::tcp::server::ConnectionProvider::createShared({privateIp, healthCheckPort, oatpp::network::Address::IP_4});
    oatpp::network::Server server(connectionProvider, connectionHandler);
    server.run();
}

int main(int argc, char *argv[])
{
    ascendLogInit();
    generateLogDir(MASTER_LOG_4_PROPERTIES_DIR);
    ::log4cplus::ConfigureAndWatchThread configureThread(MASTER_LOG_4_PROPERTIES, LOG_TIME_OUT);

    CommandParser options;
    options.addOption("-c", "./master.conf");
    options.addOption("-h");

    options.parseArgs(argc, argv);
    bool help = options.cmdOptionExists("-h");
    std::string configFileName = options.cmdGetOption("-c");

    if (help) {
        ShowUsage();
        return EXIT_SUCCESS;
    }

    struct sigaction sa;
    sa.sa_handler = SIG_IGN;
    if (sigaction(SIGPIPE, &sa, 0) < 0) {
        LOG_ERROR_FMT("Sigaction SIGPIPE failed");
    }

    if (ENC_OK != master::masterServiceStartInit(configFileName)) {
        LOG_ERROR_FMT("Master service start init failed");
        return ENC_FAIL;
    }

    oatpp::base::Environment::init();
    runHttpServer(rr::gMasterConfig.iMaster.privateIp, rr::gMasterConfig.iMaster.healthCheckUrl,
                  rr::gMasterConfig.iMaster.healthCheckPort);
    oatpp::base::Environment::destroy();
    while (true) {
        usleep(MAIN_THREAD_SLEEP_TIME);
    }

    return ENC_OK;
}